#!/bin/sh

# You can run DF under gdb by passing -g or --gdb as the first argument.
#
# If the file ".dfhackrc" exists in the DF directory or your home directory
# it will be sourced by this script, to let you set environmental variables.
# If it exists in both places it will first source the one in your home
# directory, then the one in the game directory.
#
# Shell variables .dfhackrc can set to affect this script:
#     DF_GDB_OPTS: Options to pass to gdb, if it's being run
#     DF_VALGRIND_OPTS: Options to pass to valgrind, if it's being run
#     DF_HELGRIND_OPTS: Options to pass to helgrind, if it's being run
#     DF_POST_CMD: Shell command to be run at very end of script (after DF exits)
#     DF_PRELOAD: Colon-separated list of libraries to preload with LD_PRELOAD

DF_DIR=$(dirname "$0")
cd "${DF_DIR}"

# User config files
RC=".dfhackrc"

if [ -r "$HOME/$RC" ]; then
    . $HOME/$RC
fi
if [ -r "./$RC" ]; then
    . "./$RC"
fi

if [ ! -t 0 ]; then
    stty() {
        return
    }
fi

# Save current terminal settings
old_tty_settings=$(stty -g)

# Now run
export LD_LIBRARY_PATH=".:$LD_LIBRARY_PATH"

if which objdump > /dev/null; then
  DFHACK_LIB="./hack/libdfhack.so"
  LIBSAN="$(objdump -p $DFHACK_LIB | sed -n 's/^.*NEEDED.*\(lib[a-z]san[a-z.0-9]*\).*$/\1/p' | head -n1):"
  if [ ":" != "${LIBSAN}" ]; then
    DF_PRELOAD="${DF_PRELOAD:+$DF_PRELOAD:}${LIBSAN}"
    echo "preloading sanitizer: ${LIBSAN}"
  fi
fi

setarch_arch=$(cat hack/dfhack_setarch.txt || printf x86_64)
if ! setarch "$setarch_arch" -R true 2>/dev/null; then
    echo "warn: architecture '$setarch_arch' not supported by setarch" >&2
    if [ "$setarch_arch" = "i386" ]; then
        setarch_arch=linux32
    else
        setarch_arch=linux64
    fi
    echo "using '$setarch_arch' instead. To silence this warning, edit" >&2
    echo "hack/dfhack_setarch.txt to contain an architecture that works on your system." >&2
fi

case "$1" in
  -g | --gdb)
    shift
    echo "set exec-wrapper env LD_LIBRARY_PATH='$LD_LIBRARY_PATH' LD_PRELOAD='${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD' MALLOC_PERTURB_=45" > gdbcmd.tmp
    echo "set print thread-events off" >> gdbcmd.tmp
    gdb $DF_GDB_OPTS -x gdbcmd.tmp --args ./dwarfort "$@"
    rm gdbcmd.tmp
    ret=$?
    ;;
  -r | --remotegdb)
    shift
    if [ "$#" -gt 0 ]; then
      echo "****"
      echo "gdbserver doesn't support spaces in arguments."
      echo "If your world gen name has spaces you need to remove spaces from the name in data/init/world_gen.txt"
      echo "****"
    fi
    echo "set environment LD_LIBRARY_PATH $LD_LIBRARY_PATH" > gdbcmd.tmp
    echo "set environment LD_PRELOAD $DF_PRELOAD" >> gdbcmd.tmp
    echo "set environment MALLOC_PERTURB_ 45" >> gdbcmd.tmp
    echo "set startup-with-shell off" >> gdbcmd.tmp
    echo "target extended-remote localhost:12345" >> gdbcmd.tmp
    echo "set remote exec-file ./dwarfort" >> gdbcmd.tmp
    # For some reason gdb ignores sysroot setting if it is from same file as
    # target extended-remote command
    echo "set sysroot /" > gdbcmd_sysroot.tmp
    gdb $DF_GDB_OPTS -x gdbcmd.tmp -x gdbcmd_sysroot.tmp --args ./dwarfort "$@"
    rm gdbcmd.tmp gdbcmd_sysroot.tmp
    ret=$?
    ;;
  -s | --gdbserver) # -s for server
    shift
    echo "Starting gdbserver in multi mode."
    echo "To exit the gdbserver you can enter 'monitor exit' command to gdb or use kill signal"
    gdbserver --multi localhost:12345
    ret=$?
    ;;
  -h | --helgrind)
    shift
    LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" setarch "$setarch_arch" -R valgrind $DF_HELGRIND_OPTS --tool=helgrind --log-file=helgrind.log ./dwarfort "$@"
    ret=$?
    ;;
  -v | --valgrind)
    shift
    LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" setarch "$setarch_arch" -R valgrind $DF_VALGRIND_OPTS --log-file=valgrind.log ./dwarfort "$@"
    ret=$?
    ;;
  -c | --callgrind)
    shift
    LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" setarch "$setarch_arch" -R valgrind $DF_CALLGRIND_OPTS --tool=callgrind --separate-threads=yes --dump-instr=yes --instr-atstart=no --log-file=callgrind.log ./dwarfort "$@"
    ret=$?
    ;;
  --strace)
    shift
    strace -f setarch "$setarch_arch" -R env LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" ./dwarfort "$@" 2> strace.log
    ret=$?
    ;;
  -x | --exec)
    exec setarch "$setarch_arch" -R env LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" ./dwarfort "$@"
    # script does not resume
    ;;
  --sc | --sizecheck)
    DF_PRELOAD="${DF_PRELOAD:+$DF_PRELOAD:}./hack/libsizecheck.so"
    MALLOC_PERTURB_=45 setarch "$setarch_arch" -R env LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" ./dwarfort "$@"
    ret=$?
    ;;
  *)
    TARGET=./dwarfort
    if [ "$SteamAppId" = 2346660 ]; then
      TARGET=hack/launchdf
    fi
    setarch "$setarch_arch" -R env LD_PRELOAD="${LD_PRELOAD:+$LD_PRELOAD:}$DF_PRELOAD" $TARGET "$@"
    ret=$?
    ;;
esac

# Restore previous terminal settings
stty "$old_tty_settings"
tput sgr0
echo

if [ -n "$DF_POST_CMD" ]; then
    eval $DF_POST_CMD
fi

exit $ret
